#!/usr/bin/env python3
"""
Web应用集成示例
演示如何在Flask Web应用中集成统一日志模块
"""

import asyncio
import time
from datetime import datetime
from typing import Dict, Any
from flask import Flask, request, jsonify, g
import uuid
from unified_logger import AsyncUnifiedLogger, LogLevel


class WebLogger:
    """Web应用专用日志器"""
    
    def __init__(self):
        self.logger = None
        
    async def initialize(self):
        """初始化日志器"""
        self.logger = AsyncUnifiedLogger(
            name="web_app",
            log_level=LogLevel.INFO,
            enable_console=True,
            enable_file=True,
            log_file="logs/web_app.log"
        )
        await self.logger.start()
        
    async def log_request(self, request_id: str, method: str, path: str, 
                         client_ip: str, user_agent: str):
        """记录请求信息"""
        await self.logger.info(
            "HTTP请求",
            extra={
                "request_id": request_id,
                "method": method,
                "path": path,
                "client_ip": client_ip,
                "user_agent": user_agent,
                "timestamp": datetime.utcnow().isoformat()
            }
        )
        
    async def log_response(self, request_id: str, status_code: int, 
                          duration_ms: float, response_size: int = None):
        """记录响应信息"""
        await self.logger.info(
            "HTTP响应",
            extra={
                "request_id": request_id,
                "status_code": status_code,
                "duration_ms": duration_ms,
                "response_size": response_size,
                "timestamp": datetime.utcnow().isoformat()
            }
        )
        
    async def log_error(self, request_id: str, error_type: str, 
                       error_message: str, stack_trace: str = None):
        """记录错误信息"""
        await self.logger.error(
            "应用错误",
            extra={
                "request_id": request_id,
                "error_type": error_type,
                "error_message": error_message,
                "stack_trace": stack_trace,
                "timestamp": datetime.utcnow().isoformat()
            }
        )


# 创建Flask应用
app = Flask(__name__)
web_logger = WebLogger()


@app.before_request
def before_request():
    """请求前处理"""
    g.request_id = str(uuid.uuid4())
    g.start_time = time.time()
    
    # 记录请求信息
    asyncio.create_task(web_logger.log_request(
        request_id=g.request_id,
        method=request.method,
        path=request.path,
        client_ip=request.remote_addr,
        user_agent=request.headers.get('User-Agent', '')
    ))


@app.after_request
def after_request(response):
    """请求后处理"""
    duration_ms = (time.time() - g.start_time) * 1000
    
    # 记录响应信息
    asyncio.create_task(web_logger.log_response(
        request_id=g.request_id,
        status_code=response.status_code,
        duration_ms=duration_ms,
        response_size=response.content_length
    ))
    
    # 添加请求ID到响应头
    response.headers['X-Request-ID'] = g.request_id
    return response


@app.route('/api/users/<int:user_id>')
async def get_user(user_id: int):
    """获取用户信息"""
    try:
        # 模拟数据库查询
        await asyncio.sleep(0.1)
        
        if user_id == 999:
            # 模拟错误
            raise ValueError("用户不存在")
            
        user_data = {
            "id": user_id,
            "username": f"user_{user_id}",
            "email": f"user_{user_id}@example.com",
            "created_at": "2024-01-01T00:00:00Z"
        }
        
        # 记录业务操作
        await web_logger.logger.info(
            "获取用户信息",
            extra={
                "request_id": g.request_id,
                "user_id": user_id,
                "operation": "user_retrieval"
            }
        )
        
        return jsonify(user_data)
        
    except Exception as e:
        await web_logger.log_error(
            request_id=g.request_id,
            error_type=type(e).__name__,
            error_message=str(e)
        )
        return jsonify({"error": str(e)}), 500


@app.route('/api/users', methods=['POST'])
async def create_user():
    """创建新用户"""
    try:
        data = request.get_json()
        
        # 验证输入
        if not data or 'username' not in data:
            raise ValueError("用户名不能为空")
            
        # 模拟创建用户
        await asyncio.sleep(0.2)
        
        new_user = {
            "id": 12345,
            "username": data['username'],
            "email": data.get('email', f"{data['username']}@example.com"),
            "created_at": datetime.utcnow().isoformat()
        }
        
        # 记录业务操作
        await web_logger.logger.info(
            "创建用户",
            extra={
                "request_id": g.request_id,
                "username": data['username'],
                "email": data.get('email'),
                "operation": "user_creation"
            }
        )
        
        return jsonify(new_user), 201
        
    except Exception as e:
        await web_logger.log_error(
            request_id=g.request_id,
            error_type=type(e).__name__,
            error_message=str(e)
        )
        return jsonify({"error": str(e)}), 400


@app.route('/health')
async def health_check():
    """健康检查"""
    health_data = {
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat(),
        "uptime": time.time()
    }
    
    await web_logger.logger.debug(
        "健康检查",
        extra={
            "request_id": g.request_id,
            "status": "healthy"
        }
    )
    
    return jsonify(health_data)


async def main():
    """主函数"""
    # 初始化日志器
    await web_logger.initialize()
    
    try:
        print("Web应用日志集成示例")
        print("访问以下端点测试：")
        print("- GET  http://localhost:5000/api/users/123")
        print("- POST http://localhost:5000/api/users")
        print("- GET  http://localhost:5000/health")
        print("\n日志文件将保存在：logs/web_app.log")
        
        # 启动Flask应用
        app.run(host='0.0.0.0', port=5000, debug=True)
        
    finally:
        await web_logger.logger.stop()


if __name__ == "__main__":
    asyncio.run(main())